package com.systop.tea.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.systop.tea.common.R;
import com.systop.tea.dto.OrderDto;
import com.systop.tea.dto.OrderDto2;
import com.systop.tea.dto.OrderItemDto;
import com.systop.tea.entity.Address;
import com.systop.tea.entity.Order;
import com.systop.tea.entity.OrderItem;
import com.systop.tea.entity.Product;
import com.systop.tea.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.stream.Collectors;

@RestController
@RequiredArgsConstructor
@RequestMapping("/order")
public class OrderController {

    private final OrderService orderService;
    private final OrderItemService orderItemService;
    private final ProductService productService;
    private final AddressService addressService;

    @GetMapping("/page")
    public R<Page> page(Order order, Integer pageNum, Integer pageSize) {
        Page<Order> pageInfo = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(order.getOrderId() != null, Order::getOrderId, order.getOrderId());
        queryWrapper.eq(order.getStatus() != null, Order::getStatus, order.getStatus());
        queryWrapper.orderByDesc(Order::getUpdated);
        orderService.page(pageInfo, queryWrapper);

        Page<OrderDto2> orderDto2Page = new Page<>();
        BeanUtils.copyProperties(pageInfo, orderDto2Page, "records");

        List<Order> records = pageInfo.getRecords();
        List<OrderDto2> list = records.stream().map(item -> {
            OrderDto2 orderDto2 = new OrderDto2();
            BeanUtils.copyProperties(item, orderDto2);
            Address address = addressService.getById(item.getAddressId());
            if (address != null) {
                orderDto2.setName(address.getName());
                orderDto2.setPhone(address.getPhone());
                orderDto2.setAddress(address.getArea() + address.getDetail());
            }
            return orderDto2;
        }).collect(Collectors.toList());

        orderDto2Page.setRecords(list);
        return R.success(orderDto2Page);
    }

    @GetMapping("/query")
    public R<Page> query(Order order, Integer pageNum, Integer pageSize) {
        Page<Order> pageInfo = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(order.getUserId() != null, Order::getUserId, order.getUserId());
        queryWrapper.eq(order.getStatus() != null, Order::getStatus, order.getStatus());
        queryWrapper.orderByDesc(Order::getUpdated);
        orderService.page(pageInfo, queryWrapper);

        Page<OrderDto> orderDtoPage = new Page<>();
        BeanUtils.copyProperties(pageInfo, orderDtoPage, "records");

        List<Order> records = pageInfo.getRecords();
        List<OrderDto> orderDtos = records.stream().map(item -> {
            OrderDto orderDto = new OrderDto();
            BeanUtils.copyProperties(item, orderDto);
            LambdaQueryWrapper<OrderItem> itemQueryWrapper = new LambdaQueryWrapper<>();
            itemQueryWrapper.eq(OrderItem::getOrderId, item.getOrderId());
            List<OrderItem> itemList = orderItemService.list(itemQueryWrapper);

            List<OrderItemDto> orderItemDtos = itemList.stream().map(orderItem -> {
                OrderItemDto orderItemDto = new OrderItemDto();
                BeanUtils.copyProperties(orderItem, orderItemDto);
                Product product = productService.getById(orderItem.getProductId());
                if (product != null) {
                    orderItemDto.setProductName(product.getProductName());
                    orderItemDto.setThumbnail(product.getThumbnail());
                    orderItemDto.setReprice(product.getReprice());
                }

                return orderItemDto;
            }).collect(Collectors.toList());

            orderDto.setItems(orderItemDtos);

            return orderDto;
        }).collect(Collectors.toList());

        orderDtoPage.setRecords(orderDtos);
        return R.success(orderDtoPage);
    }

    @GetMapping("/{id}")
    public R<OrderDto> queryById(@PathVariable Integer id) {
        Order order = orderService.getById(id);
        OrderDto orderDto = new OrderDto();
        BeanUtils.copyProperties(order, orderDto);

        LambdaQueryWrapper<OrderItem> itemQueryWrapper = new LambdaQueryWrapper<>();
        itemQueryWrapper.eq(OrderItem::getOrderId, order.getOrderId());
        List<OrderItem> itemList = orderItemService.list(itemQueryWrapper);

        List<OrderItemDto> orderItemDtos = itemList.stream().map(orderItem -> {
            OrderItemDto orderItemDto = new OrderItemDto();
            BeanUtils.copyProperties(orderItem, orderItemDto);
            Product product = productService.getById(orderItem.getProductId());
            if (product != null) {
                orderItemDto.setProductName(product.getProductName());
                orderItemDto.setThumbnail(product.getThumbnail());
                orderItemDto.setReprice(product.getReprice());
            }

            return orderItemDto;
        }).collect(Collectors.toList());

        orderDto.setItems(orderItemDtos);
        return R.success(orderDto);
    }

    @PostMapping
    @Transactional
    public R<String> add(@RequestBody OrderDto orderDto) {
        orderDto.setCreated(LocalDateTime.now());
        orderDto.setUpdated(LocalDateTime.now());
        orderDto.setShippingCode(String.valueOf(new Random().nextLong()));
        orderDto.setShippingName("顺丰物流");
        boolean row = orderService.save(orderDto);
        Integer orderId = orderDto.getOrderId();
        List<OrderItemDto> items = orderDto.getItems();

        List<OrderItem> orderItemList = items.stream().map(item -> {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(orderId);
            orderItem.setProductId(item.getProductId());
            orderItem.setCount(item.getCount());
            return orderItem;
        }).collect(Collectors.toList());

        boolean row1= orderItemService.saveBatch(orderItemList);
        if (row && row1) {
            if (orderDto.getStatus() == 1) {
                cancelOrder(orderDto);
            }

            return R.success("订单添加成功");
        } else {
            return R.error("订单添加失败");
        }
    }

    @PutMapping
    public R<String> modify(@RequestBody OrderDto orderDto) {
        orderDto.setUpdated(LocalDateTime.now());
        boolean row = orderService.updateById(orderDto);
        if (row) {
            return R.success("订单修改成功");
        } else {
            return R.error("订单修改失败");
        }
    }

    @DeleteMapping("/{id}")
    @Transactional
    public R<String> delete(@PathVariable Integer id) {
        boolean row = orderService.removeById(id);
        LambdaQueryWrapper<OrderItem> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderItem::getOrderId, id);
        boolean row1 = orderItemService.remove(queryWrapper);

        if (row && row1) {
            return R.success("订单删除成功");
        } else {
            return R.error("订单删除失败");
        }
    }

    // 定时取消订单
    public void cancelOrder(OrderDto orderDto) {
        orderDto.setUpdated(LocalDateTime.now());
        orderDto.setStatus(0);
        System.out.println(LocalDateTime.now() + "开启定时取消");
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                System.out.println(LocalDateTime.now() + "订单取消");
                orderService.updateById(orderDto);
            }
        };
        Timer timer = new Timer();
        timer.schedule(task, 15 * 60 * 1000);
    }

}
